pytestでgit diffの差分があるファイルだけをテストしてみる
PythonでLambdaを書いているとき、pytestを利用してUnit TestやAPIに対するE2Eテストを実施しています。 Lambdaが多くなるほど、実施するテストも増えます。 実施するテストが増えると、1回あたりのCI/CDの稼働時間も増えます。
このCI/CDの稼働時間を減らすために、差分があるLambdaのテストだけを実施する仕組みを考えてみました。 (ALLのテストはデイリーで実施する想定です。)
おすすめの方
- pytestでgit diffの差分があるファイルだけをテストしてみたい方
前提
次のフォルダ構成とします。「handlers/xxx」とペアになるe2eテストファイルがあります。
├── src │ └── handlers │ ├── xxx │ │ └── app.py │ └── yyy │ └── app.py └── tests └── e2e ├── test_xxx.py └── test_yyy.py
まずは、普通にE2E Testを実行する
Pythonコード(src)
用意はしますが、ダミーです。
src/handlers/xxx/app.py
def message(): return "this is xxx/app.py"
src/handlers/yyy/app.py
def message(): return "this is yyy/app.py"
Pythonコード(e2e test)
実際はデプロイしたAPIのエンドポイントなどを叩く想定ですが、ここでは「assert True」としておきます。
tests/e2e/test_xxx.py
def test_message(): assert True
tests/e2e/test_yyy.py
def test_message(): assert True
E2E Testを実行する
次のコマンドで実行すると、2つのE2E Testが実行されます。(結果は一部抜粋しています)
pytest tests/e2e
collected 2 items tests/e2e/test_xxx.py . [ 50%] tests/e2e/test_yyy.py . [100%] ============================== 2 passed in 0.01s ===============================
git diffで差分のあるファイルだけテストする
テスト用のスクリプト
git diffで「src/handlers配下」と「tests/e2e配下」の差分ファイル名を取得し、テストファイルを特定し、重複を削除して、pytestを実行します。 スクリプト力が高くないので散らかってますが……。
#!/bin/bash git diff main --name-only echo --- # src/handlers配下の差分ファイル名を取得する src_files=$(git diff main --name-only | grep "^src/handlers/.*\.py$") # 対応するテストファイル名を取得する src_test_files=$(for file in $src_files; do echo $file | sed -E 's|src/handlers/([^/]+)/([^/]+\.py)$|tests/e2e/test_\1.py|'; done) # tests/e2e配下の差分ファイル名を取得する e2e_test_files=$(git diff main --name-only | grep "^tests/e2e/.*\.py$") # 重複を削除する target_files=$((echo $src_test_files; echo $e2e_test_files) | tr ' ' '\n' | sort -u) # テストファイルがない場合は終了する if [ -z "$target_files" ]; then echo "No test files" exit 0 fi pytest $target_files
テストを実行する
diffなし
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
No test files
diffあり(src配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 1 item tests/e2e/test_xxx.py . [100%]
diffあり(src配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 1 item tests/e2e/test_yyy.py . [100%]
diffあり(src配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 2 items tests/e2e/test_xxx.py . [ 50%] tests/e2e/test_yyy.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分なし
collected 1 item tests/e2e/test_xxx.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分あり
collected 1 item tests/e2e/test_yyy.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分あり
collected 2 items tests/e2e/test_xxx.py . [ 50%] tests/e2e/test_yyy.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分なし
collected 1 item tests/e2e/test_xxx.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分あり
collected 2 items tests/e2e/test_xxx.py . [ 50%] tests/e2e/test_yyy.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分あり
collected 2 items tests/e2e/test_xxx.py . [ 50%] tests/e2e/test_yyy.py . [100%]
さいごに
git diffコマンドで差分があるファイルのテストを実行してみました。 命名の前提があったりで小回りは効きませんが、ここからカスタマイズしてみるのも良いですね。